﻿using ConsoleHoster.Common.Utilities.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using TestUtilities;


namespace ConsoleHoster.UnitTests.ModelTests.SuggestionsTests
{
	[TestClass]
	public class DirectoryContentProviderTests
	{
		private FileSystemContentProvider tmpProvider;

		[TestInitialize]
		public void Initialize()
		{
			this.tmpProvider = new FileSystemContentProvider();
		}

		[TestMethod]
		public void FolderExists_ReturnsFalseForNonExistingDirectory()
		{
			Assert.IsFalse(tmpProvider.DirectoryExists(Guid.NewGuid().ToString()));
		}

		[TestMethod]
		public void FolderExists_ReturnsTrueForExistingFolder()
		{
			Assert.IsTrue(tmpProvider.DirectoryExists("C:\\Windows"));
		}

		[TestMethod]
		public void GetAllItems_QueryWithNullPatternRetrievesListOfAllItemsInDirectory()
		{
			const string tmpDirectory = "C:";

			string[] tmpActualItems = tmpProvider.GetAllItems(tmpDirectory, null);
			string[] tmpExpectedItems = Directory.GetFileSystemEntries(tmpDirectory);

			Assert.IsNotNull(tmpActualItems);
			AssertExtensions.ArraysEqual(tmpExpectedItems, tmpActualItems);
		}

		[TestMethod]
		public void GetAllItems_QueryWithEmptyPatternRetrievesListOfAllItemsInDirectory()
		{
			const string tmpDirectory = "C:";

			string[] tmpActualItems = tmpProvider.GetAllItems(tmpDirectory, String.Empty);
			string[] tmpExpectedItems = Directory.GetFileSystemEntries(tmpDirectory);

			Assert.IsNotNull(tmpActualItems);
			AssertExtensions.ArraysEqual(tmpExpectedItems, tmpActualItems);
		}

		[TestMethod]
		public void GetAllItems_QueryWithPatternWithoutAsteriskInTheEndRetrievesListOfMatchingItemsInDirectory()
		{
			const string tmpDirectory = "C:";
			const string tmpPattern = "a";

			string[] tmpActualItems = tmpProvider.GetAllItems(tmpDirectory, tmpPattern);
			string[] tmpExpectedItems = Directory.GetFileSystemEntries(tmpDirectory, String.Format("{0}*", tmpPattern));

			Assert.IsNotNull(tmpActualItems);
			AssertExtensions.ArraysEqual(tmpExpectedItems, tmpActualItems);
		}

		[TestMethod]
		public void GetAllItems_QueryWithPatternWithAsteriskInTheEndRetrievesListOfMatchingItemsInDirectory()
		{
			const string tmpDirectory = "C:";
			const string tmpPattern = "a*";

			string[] tmpActualItems = tmpProvider.GetAllItems(tmpDirectory, tmpPattern);
			string[] tmpExpectedItems = Directory.GetFileSystemEntries(tmpDirectory, tmpPattern);

			Assert.IsNotNull(tmpActualItems);
			AssertExtensions.ArraysEqual(tmpExpectedItems, tmpActualItems);
		}

		[TestMethod]
		public void GetFolders_QueryWithNullPatternRetrievesListOfAllItemsInDirectory()
		{
			const string tmpDirectory = "C:";

			string[] tmpActualItems = tmpProvider.GetFolders(tmpDirectory, null);
			string[] tmpExpectedItems = Directory.GetDirectories(tmpDirectory);

			Assert.IsNotNull(tmpActualItems);
			AssertExtensions.ArraysEqual(tmpExpectedItems, tmpActualItems);
		}

		[TestMethod]
		public void GetFolders_QueryWithEmptyPatternRetrievesListOfAllItemsInDirectory()
		{
			const string tmpDirectory = "C:";

			string[] tmpActualItems = tmpProvider.GetFolders(tmpDirectory, String.Empty);
			string[] tmpExpectedItems = Directory.GetDirectories(tmpDirectory);

			Assert.IsNotNull(tmpActualItems);
			AssertExtensions.ArraysEqual(tmpExpectedItems, tmpActualItems);
		}

		[TestMethod]
		public void GetFolders_QueryWithPatternWithoutAsteriskInTheEndRetrievesListOfMatchingItemsInDirectory()
		{
			const string tmpDirectory = "C:";
			const string tmpPattern = "a";

			string[] tmpActualItems = tmpProvider.GetFolders(tmpDirectory, tmpPattern);
			string[] tmpExpectedItems = Directory.GetDirectories(tmpDirectory, String.Format("{0}*", tmpPattern));

			Assert.IsNotNull(tmpActualItems);
			AssertExtensions.ArraysEqual(tmpExpectedItems, tmpActualItems);
		}

		[TestMethod]
		public void GetFolders_QueryWithPatternWithAsteriskInTheEndRetrievesListOfMatchingItemsInDirectory()
		{
			const string tmpDirectory = "C:";
			const string tmpPattern = "a*";

			string[] tmpActualItems = tmpProvider.GetFolders(tmpDirectory, tmpPattern);
			string[] tmpExpectedItems = Directory.GetDirectories(tmpDirectory, tmpPattern);

			Assert.IsNotNull(tmpActualItems);
			AssertExtensions.ArraysEqual(tmpExpectedItems, tmpActualItems);
		}

		[TestMethod]
		public void GetDrives_ReturnsAllAvailableDrives()
		{
			IEnumerable<DriveInfo> tmpActualItems = tmpProvider.GetAvailableDrives();
			DriveInfo[] tmpExpectedItems = DriveInfo.GetDrives();

			AssertExtensions.ArraysEqual<string>(tmpExpectedItems.Select(item => item.Name), tmpActualItems.Select(item => item.Name));
		}

		[TestMethod]
		public void EnumerateFolders_EnumeratesEveryFolder()
		{
			const string tmpPath = "C:\\Windows";

			IEnumerable<string> tmpActual = tmpProvider.EnumerateFolders(tmpPath);
			IEnumerable<string> tmpExpected = Directory.EnumerateDirectories(tmpPath);
			AssertExtensions.ArraysEqual(tmpExpected, tmpActual);
		}

		[TestMethod]
		public void EnumerateFiles_EnumeratesEveryFile()
		{
			const string tmpPath = "C:\\Windows";

			IEnumerable<string> tmpActual = tmpProvider.EnumerateFiles(tmpPath);
			IEnumerable<string> tmpExpected = Directory.EnumerateFiles(tmpPath);

			AssertExtensions.ArraysEqual(tmpExpected, tmpActual);
		}

		[TestMethod]
		public void GetCurrentDirectory_ReturnsCurrentDirectory()
		{
			Assert.AreEqual(Directory.GetCurrentDirectory(), tmpProvider.GetCurrentDirectory());
		}

		[TestMethod]
		public void DirectoryExists_ReturnsTrueForExistingDirecotry()
		{
			string[] tmpDirectories = Directory.GetDirectories("C:\\Windows");

			foreach (string tmpDirectory in tmpDirectories)
			{
				Assert.IsTrue(tmpProvider.DirectoryExists(tmpDirectory));
			}
		}

		[TestMethod]
		public void DirectoryExists_ReturnsFalseForNonExistingDirectory()
		{
			Assert.IsFalse(tmpProvider.DirectoryExists(Guid.NewGuid().ToString()));
		}

		[TestMethod]
		public void CreateDirectory_CreatesDirectoryInTheGivenFolder()
		{
			string tmpCurrentDirectory = Directory.GetCurrentDirectory();

			string tmpName = Guid.NewGuid().ToString().Replace("-", String.Empty).Substring(0, 7);

			string tmpFullPath = Path.Combine(tmpCurrentDirectory, tmpName);
			tmpProvider.CreateDirectory(tmpFullPath);

			Assert.IsTrue(Directory.Exists(tmpFullPath));

			Directory.Delete(tmpFullPath);
		}
	}
}
